]> git.neil.brown.name Git - wiggle.git/blob - load.c
Move save functions to vpatch.c
[wiggle.git] / load.c
1 /*
2  * wiggle - apply rejected patches
3  *
4  * Copyright (C) 2003 Neil Brown <neilb@cse.unsw.edu.au>
5  * Copyright (C) 2013 Neil Brown <neilb@suse.de>
6  *
7  *
8  *    This program is free software; you can redistribute it and/or modify
9  *    it under the terms of the GNU General Public License as published by
10  *    the Free Software Foundation; either version 2 of the License, or
11  *    (at your option) any later version.
12  *
13  *    This program is distributed in the hope that it will be useful,
14  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *    GNU General Public License for more details.
17  *
18  *    You should have received a copy of the GNU General Public License
19  *    along with this program.
20  *
21  *    Author: Neil Brown
22  *    Email: <neilb@suse.de>
23  */
24
25 /*
26  * read in files
27  *
28  * Files are read in whole and stored in a
29  * struct stream {char*, len}
30  *
31  *
32  * loading the file "-" reads from stdin which might require
33  * reading into several buffers
34  */
35
36 #include        "wiggle.h"
37 #include        <sys/types.h>
38 #include        <sys/stat.h>
39 #include        <unistd.h>
40 #include        <fcntl.h>
41 #include        <stdlib.h>
42
43 static void join_streams(struct stream list[], int cnt)
44 {
45         /* join all the streams in the list (upto body=NULL)
46          * into one by re-allocing list[0].body and copying
47          */
48         int len = 0;
49         int i;
50         char *c;
51
52         for (i = 0; i < cnt ; i++)
53                 len += list[i].len;
54
55         c = realloc(list[0].body, len+1);
56         if (c == NULL)
57                 die("memory allocation");
58
59         list[0].body = c;
60         c  += list[0].len;
61         list[0].len = len;
62         for (i = 1; i < cnt; i++) {
63                 memcpy(c, list[i].body, list[i].len);
64                 c += list[i].len;
65                 list[i].len = 0;
66                 free(list[i].body);
67         }
68         c[0] = 0;
69 }
70
71 static struct stream load_regular(int fd)
72 {
73         struct stat stb;
74         struct stream s;
75         fstat(fd, &stb);
76
77         s.len = stb.st_size;
78         s.body = xmalloc(s.len+1);
79         if (read(fd, s.body, s.len) != s.len)
80                 die("file read");
81
82         s.body[s.len] = 0;
83         return s;
84 }
85
86 static struct stream load_other(int fd)
87 {
88
89         struct stream list[10];
90         int i = 0;
91
92         while (1) {
93                 list[i].body = xmalloc(8192);
94                 list[i].len = read(fd, list[i].body, 8192);
95                 if (list[i].len < 0)
96                         die("file read");
97                 if (list[i].len == 0)
98                         break;
99                 i++;
100                 if (i == 10) {
101                         join_streams(list, i);
102                         i = 1;
103                 }
104         }
105         join_streams(list, i);
106         return list[0];
107 }
108
109 struct stream load_segment(FILE *f,
110                            unsigned int start, unsigned int end)
111 {
112         struct stream s;
113         s.len = end - start;
114         s.body = xmalloc(s.len+1);
115         fseek(f, start, 0);
116         if (fread(s.body, 1, s.len, f) != (size_t)s.len)
117                 die("file read");
118         /* ensure string is 'nul' terminated - for sscanf */
119         s.body[s.len] = 0;
120         return s;
121 }
122
123 struct stream load_file(char *name)
124 {
125         struct stream s;
126         struct stat stb;
127         int fd;
128         int start, end;
129         int prefix_len = 0;
130
131         s.body = NULL;
132         s.len = 0;
133         if (sscanf(name, "_wiggle_:%d:%d:%n", &start, &end,
134                    &prefix_len) >= 2 && prefix_len > 0) {
135                 FILE *f = fopen(name + prefix_len, "r");
136                 if (f) {
137                         s = load_segment(f, start, end);
138                         fclose(f);
139                 } else {
140                         s.body = NULL;
141                         s.len = 0;
142                 }
143         } else {
144                 if (strcmp(name, "-") == 0)
145                         fd = 0;
146                 else {
147                         fd = open(name, O_RDONLY);
148                         if (fd < 0)
149                                 return s;
150                 }
151                 check_dir(name, fd);
152                 if (fstat(fd, &stb) == 0) {
153
154                         if (S_ISREG(stb.st_mode))
155                                 s = load_regular(fd);
156                         else
157                                 s = load_other(fd);
158                 }
159                 close(fd);
160         }
161         return s;
162 }
163